from pathlib import Path
from typing import TYPE_CHECKING, Any, Literal
import numpy
import pandas
import yaml
from pydantic import BaseModel, Field, field_validator
from .terminologies import Units
from .results import SingleResult, UnitResult

current_dir: Any
config_file_path: Any
config: Any

class SerializableDict(dict):
    """A dictionary that automatically converts non-serializable numpy values."""
    def __setitem__(self, key: Any, value: Any) -> Any:
        """Override setitem to clean values before storing."""
        ...
    def update(self, *args, **kwargs) -> Any:
        """Override update to clean values before storing."""
        ...

class GdimWidgetDataStructure:
    """
    The widget data structure in GDIM table with configurable validation capabilities.
    
    This class provides widget metadata and validation functionality for GDIM table data.
    It supports both individual value validation and efficient DataFrame column validation
    using vectorized pandas operations where possible.
    
    The validation system offers two independent configuration dimensions:
    
    1. DateTime Strictness (strict_datetime_validation):
       - True: Regex + datetime parsing validation (slower, 100% accurate)
       - False: Regex-only validation (faster, ~99.9% accurate)
    
    2. Validation Level (validation_level):
       - "full": Complete structural validation for complex types (file, address, texture)
       - "fast": Basic type checking only for complex types (faster)
    
    Performance Matrix (truly independent settings):
    - validation_level="fast" + strict_datetime_validation=False: Maximum speed
    - validation_level="fast" + strict_datetime_validation=True: Fast structures + accurate dates
    - validation_level="full" + strict_datetime_validation=False: Complete structures + fast dates
    - validation_level="full" + strict_datetime_validation=True: Maximum accuracy (default)
    """
    all_widgets: Any
    data_format_configs: Any
    def __init__(self, strict_datetime_validation: bool = True, validation_level: Literal[Any, Any] = "full"):
        """
        Initialize the widget data structure.
        
        Args:
            strict_datetime_validation: If True, use regex + datetime parsing validation (slower, more accurate).
                                      If False, use regex-only validation (faster, slightly less accurate).
                                      Default is True for data quality.
            validation_level: Validation complexity level:
                            - "fast": Only vectorized operations + basic type checks (fastest)
                            - "full": Complete validation including complex structure checks (slower, most accurate)
                            Default is "full" for maximum data quality.
        """
        ...
    @property
    def widget_names(self) -> list[str]:
        """The names of the widgets."""
        ...
    @property
    def widget_titles(self) -> list[str]:
        """The titles of the widgets."""
        ...
    @property
    def widget_data_types(self) -> list[str]:
        """The data types of the widgets."""
        ...
    def get_regex_pattern(cls, pattern: str):
        """Get compiled regex pattern with caching for efficiency."""
        ...
    def validate_single_value(self, widget_type: str, value: any, data_format: Any = None) -> bool:
        """
        Validate a single value for a specific widget type.
        
        Args:
            widget_type: The type of widget (e.g., 'input', 'number', 'dateTime')
            value: The value to validate
            data_format: Optional data format specification for the widget
        
        Returns:
            bool: True if the value is valid for the widget type, False otherwise
        """
        ...
    def validate_series(self, widget_type: str, series: pd.Series, data_format: Any = None) -> pd.Series:
        """
        Validate a pandas Series for a specific widget type using vectorized operations.
        
        Args:
            widget_type: The type of widget (e.g., 'input', 'number', 'dateTime')
            series: The pandas Series to validate
            data_format: Optional data format specification for the widget
        
        Returns:
            pd.Series: Boolean series indicating which values are valid
        """
        ...
    def validate_dataframe(self, df: pd.DataFrame, table_metadata: Any, raise_error: bool = False) -> tuple[Any, Any]:
        """
        Validate all columns in a DataFrame using table metadata.
        
        Args:
            df: The DataFrame to validate
            table_metadata: Table metadata containing field information
            raise_error: If True, raise an error if a column is not in the table metadata.
        
        Returns:
            dict: Column name -> boolean Series indicating valid rows for each column
            list: Column names that are not in the table metadata
        """
        ...
    def get_validation_summary(self, validation_results: dict[str, pd.Series]) -> dict[str, dict]:
        """
        Get a summary of validation results.
        
        Args:
            validation_results: Results from validate_dataframe
        
        Returns:
            dict: Summary including total/valid/invalid counts per column
        """
        ...

class GdimFieldMetadata(BaseModel):
    """The metadata of a field in a table."""
    name: str
    title: str
    unit: Units
    widget_type: Literal[Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any, Any]
    data_format: str | None
    field_type: Literal[Any, Any] | None
    description: str | None

class GdimTableMetaData(BaseModel):
    """The metadata of a table."""
    name: str
    title: str
    description: str | None
    table_type: Literal[Any, Any] | None
    fields_metadata: dict[str, GdimFieldMetadata]
    title_to_name: dict[str, str]
    def __init__(self, **data):
        ...
    def get_field_metadata(self, key: str) -> Any:
        """
        Get field metadata by either name or title.
        
        Args:
            key: The name or title of the field
        
        Returns:
            The field metadata if found, None otherwise
        """
        ...

class TemplateAppInfo(BaseModel):
    """The application information of a template."""
    applicationId: str
    applicationName: str
    applicationTitle: str
    applicationType: Literal[Any, Any, Any, Any, Any]
    subApp: list[_PipelineAppInfo] | None

class StandardLayerUpdate(BaseModel):
    update_method: Literal[Any, Any] | None
    define_layer_fields: list[str] | None

class GdimTemplate(BaseModel):
    """Container for table metadata with efficient name/title lookup."""
    tables: dict[str, GdimTableMetaData]
    title_to_name: dict[str, str]
    standard_layer_update: StandardLayerUpdate | None
    app_info: dict[str, TemplateAppInfo] | None
    app_title_to_name: dict[str, str]
    def __init__(self, **data):
        ...
    def get_table_metadata(self, key: str) -> Any:
        """
        Get table metadata by either name or title.
        
        Args:
            key: The name or title of the table
        
        Returns:
            The table metadata if found, None otherwise
        """
        ...
    def get_app_info(self, key: str) -> Any:
        """Get the application information by either name or title."""
        ...

class GdimTableCell(BaseModel):
    """A cell in a table."""
    value: str | int | float | bool | None
    colspan: int | None
    rowspan: int | None
    cellType: Literal[Any, Any]

class GdimJsonTable(BaseModel):
    """The data of a table to be rendered on Gdim."""
    table: list[_GdimTableRow]
    def print_table(self):
        """Print the table in a formatted way to the terminal."""
        ...

class SimpleJsonTable(BaseModel):
    """A simple table data to be rendered on Gdim."""
    name: str
    data: list[Any] | None
    columns: list[str] | None
    highlight_rows: list[int] | None
    def print_table(self):
        """Print the table in a formatted way to the terminal."""
        ...

class GdimMinIOFile(BaseModel):
    """The minIO file object."""
    success: bool
    fileId: str
    fileUrl: str | None
    originalFilename: str
    filename: str
    size: int
    contentType: str
    objectId: str | None
    objectType: str | None
    message: str | None
    thFileUrl: str | None
    thFilename: str | None
    thSize: int | None
    downloadUrl: str
    host: str | None
    @field_validator
    def convert_empty_string_to_none(cls, v):
        """Convert empty strings to None for optional string fields."""
        ...
    def get_download_url(self) -> str:
        """Get the download url of the file."""
        ...
    def get_file_url(self) -> Any:
        """Get the file url of the file."""
        ...

class ProjectAddress(BaseModel):
    """The address of the project."""
    province: str | None
    city: str | None
    district: str | None
    address: str | None
    def to_single_result_fields(self) -> list[Any]:
        """
        Convert ProjectAddress to a list of UnitResult objects for inclusion in SingleResult.
        
        Returns
        -------
        list[UnitResult]
            List of UnitResult objects representing the address fields:
            - projectAddressProvince: The province of the project
            - projectAddressCity: The city of the project
            - projectAddressDistrict: The district of the project
            - projectAddressDetail: The detailed address of the project
        """
        ...

class GdimProjectInfo(BaseModel):
    id: str
    dataTemplateId: str | None
    dataTemplateName: str | None
    projectName: str | None
    dataTemplateGroupId: str | None
    dataTemplateGroupName: str | None
    spaceId: str | None
    spaceType: Literal[Any, Any]
    projectManager: str | None
    coordinateSystem: Literal[Any, Any, Any, Any, Any, Any, Any, Any, Any, Any] | None
    zoneMethod: Literal[Any, Any] | None
    zoneNumber: int | None
    centralMeridian: float | None
    refPointLongitude: float | None
    refPointLatitude: float | None
    refPointX: float | None
    refPointY: float | None
    elevationDatum: str | None
    yAxisDirection: Literal[Any, Any] | None
    readOnly: bool
    projectAddress: ProjectAddress | None
    currentUserIsProjectManager: bool
    accessPermission: bool
    customFields: dict[str, Any]
    @field_validator
    def validate_custom_fields(cls, v: dict[str, Any]) -> SerializableDict:
        """Convert customFields to SerializableDict and clean non-serializable values."""
        ...
    def to_single_result(self) -> Any:
        """
        Convert GdimProjectInfo to a SingleResult object.
        
        This method converts all fields of the GdimProjectInfo instance into UnitResult objects
        and returns them as a SingleResult. The projectAddress field is converted to separate
        keys using the ProjectAddress.to_single_result_fields() method.
        
        Returns
        -------
        SingleResult
            A SingleResult containing all project information as UnitResult objects
        """
        ...
